﻿using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace Framework.Utils
{
    /// <summary>
    /// 加密处理
    /// </summary>
    public class EncryptUtils
    {
        #region MD5加密
        /// <summary>
        /// MD5
        /// </summary>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public static string MD5(string src)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] data = System.Text.Encoding.Default.GetBytes(src);
            byte[] md5data = md5.ComputeHash(data);
            md5.Clear();
            // 字符串转化
            StringBuilder strBdr = new StringBuilder();
            for (int i = 0; i < md5data.Length; i++)
            {
                strBdr.Append(md5data[i].ToString("x").PadLeft(2, '0'));
            }
            return strBdr.ToString();
        }
        #endregion


        public static class DES
        {

            ///DES加密   
            public static byte[] Encrypt(byte[] src, byte[] key)
            {
                //生成key
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                des.Key = key;
                des.IV = key;
                //执行加密
                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
                cs.Write(src, 0, src.Length);
                cs.FlushFinalBlock();
                //提取数据
                long bufSize = ms.Length;
                if (bufSize <= 0) { return null; }
                //提取数据
                // byte[] outBuf = new byte[bufSize];
                //ms.Read(outBuf, 0, (int)bufSize);
                byte[] outBuf = ms.ToArray();
                return outBuf;
            }
            //DES解密
            public static byte[] Decrypt(byte[] src, byte[] key)
            {
                //生成key
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                des.Key = key;
                des.IV = key;
                //解密
                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
                cs.Write(src, 0, src.Length);
                cs.FlushFinalBlock();
                //提取数据
                long bufSize = ms.Length;
                if (bufSize <= 0) { return null; }
                //提取数据
                byte[] outBuf = ms.ToArray();
                return outBuf;
            }



            /////DES加密   
            //public static string Encrypt(string pToEncrypt, string sKey)
            //{
            //    DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            //    byte[] inputByteArray = Encoding.Default.GetBytes(pToEncrypt);
            //    des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
            //    des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
            //    MemoryStream ms = new MemoryStream();
            //    CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
            //    cs.Write(inputByteArray, 0, inputByteArray.Length);
            //    cs.FlushFinalBlock();
            //    StringBuilder ret = new StringBuilder();
            //    foreach (byte b in ms.ToArray())
            //    {
            //        ret.AppendFormat("{0:X2}", b);
            //    }
            //    ret.ToString();
            //    return ret.ToString();


            //}

            /////DES解密   
            //public static string Decrypt(string pToDecrypt, string sKey)
            //{
            //    DESCryptoServiceProvider des = new DESCryptoServiceProvider();

            //    byte[] inputByteArray = new byte[pToDecrypt.Length / 2];
            //    for (int x = 0; x < pToDecrypt.Length / 2; x++)
            //    {
            //        int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16));
            //        inputByteArray[x] = (byte)i;
            //    }

            //    des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
            //    des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
            //    MemoryStream ms = new MemoryStream();
            //    CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
            //    cs.Write(inputByteArray, 0, inputByteArray.Length);
            //    cs.FlushFinalBlock();

            //    StringBuilder ret = new StringBuilder();

            //    return System.Text.Encoding.Default.GetString(ms.ToArray());
            //}




            //// 加密字符串   
            //public static string EncryptString(string src, string key)
            //{
            //    byte[] data = Encoding.UTF8.GetBytes(src);
            //    DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
            //    DES.Key = ASCIIEncoding.ASCII.GetBytes(key);
            //    DES.IV = ASCIIEncoding.ASCII.GetBytes(key);
            //    ICryptoTransform desencrypt = DES.CreateEncryptor();
            //    byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length);
            //    return BitConverter.ToString(result);
            //}

            //// 解密字符串   
            //public static string DecryptString(string sInputString, string sKey)
            //{
            //    string[] sInput = sInputString.Split("-".ToCharArray());
            //    byte[] data = new byte[sInput.Length];
            //    for (int i = 0; i < sInput.Length; i++)
            //    {
            //        data[i] = byte.Parse(sInput[i], NumberStyles.HexNumber);
            //    }
            //    DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
            //    DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
            //    DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
            //    ICryptoTransform desencrypt = DES.CreateDecryptor();
            //    byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length);
            //    return Encoding.UTF8.GetString(result);
            //}

            //public static string GenerateKey()
            //{
            //    DESCryptoServiceProvider desCrypto = (DESCryptoServiceProvider)DESCryptoServiceProvider.Create();
            //    return ASCIIEncoding.ASCII.GetString(desCrypto.Key);
            //}   
        }




        public static class Base64
        {

            public static string EncodeString(string src)
            {
                byte[] bytes = Encoding.UTF8.GetBytes(src);
                return Encode(bytes);
            }

            public static string DecodeString(string str)
            {
                try
                {
                    byte[] buffer = Decode(str);
                    return Encoding.UTF8.GetString(buffer);
                }
                catch (Exception) { }
                return null;
            }

            public static string Encode(byte[] data)
            {
                return Convert.ToBase64String(data, 0, data.Length);
            }

            public static byte[] Decode(string str)
            {
                return Convert.FromBase64String(str);
            }


        }







        public static class ZED
        {
            /** 偏移:小于256 **/
            private const byte offsetKey = 18;
            /** 变化值:小于256 **/
            private const byte indexKey = 121;
            /** 编码格式 **/
            private static readonly Encoding encoding = Encoding.UTF8;

            /** 加强加密+base64 **/
            public static string Encrypt(string src, string encryptKey)
            {
                byte[] keys = encoding.GetBytes(encryptKey);
                byte[] buffer = encoding.GetBytes(src);
                buffer = EncryptE(buffer, keys);
                // return BufferUtils.bytesToString(buffer);
                return EncryptUtils.Base64.Encode(buffer);
            }

            /** 加强解密+base64 **/
            public static string Decrypt(string src, string encryptKey)
            {
                byte[] keys = encoding.GetBytes(encryptKey);
                byte[] buffer = EncryptUtils.Base64.Decode(src);
                buffer = DecryptE(buffer, keys);
                return encoding.GetString(buffer);
            }

            /** 加强版算法加密 **/
            public static byte[] EncryptE(byte[] buffer, byte[] keys)
            {
                int v = EncryptUtils.GetCheckDigit(keys, 0, keys.Length); // 校验码
                buffer = EncryptUtils.ZED.Encrypt(buffer, keys);
                buffer = EncryptUtils.Inversion(buffer, 0, buffer.Length, v % 2, 0xFF);
                buffer = EncryptUtils.Overturn(buffer, 0, buffer.Length, v % 3);
                buffer = EncryptUtils.Offset(buffer, 0, buffer.Length, v % 2, v % 128);
                return buffer;
            }

            /** 加强版算法解密 **/
            public static byte[] DecryptE(byte[] buffer, byte[] keys)
            {
                int v = EncryptUtils.GetCheckDigit(keys, 0, keys.Length); // 校验码
                buffer = EncryptUtils.Offset(buffer, 0, buffer.Length, v % 2, -v % 128);
                buffer = EncryptUtils.Overturn(buffer, 0, buffer.Length, v % 3);
                buffer = EncryptUtils.Inversion(buffer, 0, buffer.Length, v % 2, 0xFF);
                buffer = EncryptUtils.ZED.Decrypt(buffer, keys);
                return buffer;
            }



            /** 加密 **/
            public static byte[] Encrypt(byte[] buffer, string password)
            {
                return Encrypt(buffer, Encoding.UTF8.GetBytes(password));
            }

            /** 加密 **/
            public static byte[] Encrypt(byte[] buffer, byte[] keys)
            {
                // 创建数据体
                int bufSize = (buffer != null) ? buffer.Length : 0;
                byte[] out0 = new byte[bufSize]; // 新数据
                // 加密
                Encrypt(buffer, keys, out0, 0);
                return out0;
            }

            /** 加密 **/
            public static int Encrypt(byte[] buffer, byte[] keys, byte[] out0, int offset)
            {
                // 密码数据
                int bufSize = (buffer != null) ? buffer.Length : 0;
                int keySize = (keys != null) ? keys.Length : 0;

                // 遍历处理
                for (int i = 0; i < bufSize; i++)
                {
                    byte b = buffer[i];
                    byte index = (byte)(indexKey - (i % indexKey));
                    byte c = (keySize > 0) ? keys[i % keySize] : (byte)0;
                    c += index;
                    // 数据偏移
                    b = (byte)((b + (offsetKey + keySize + c) + 256) % 256);
                    // 数据转化
                    b = (byte)(b ^ c);
                    // 设置数据
                    out0[i + offset] = b;
                }
                return bufSize + offset;
            }

            /** 解密 **/
            public static byte[] Decrypt(byte[] buffer, string password)
            {
                return Decrypt(buffer, Encoding.UTF8.GetBytes(password));
            }

            /** 解密 **/
            public static byte[] Decrypt(byte[] buffer, byte[] keys)
            {
                // 创建数据体
                int bufSize = (buffer != null) ? buffer.Length : 0;
                byte[] out0 = new byte[bufSize];

                // 解密
                Decrypt(buffer, keys, out0, 0);
                return out0;
            }

            /** 解密 **/
            public static int Decrypt(byte[] buffer, byte[] keys, byte[] out0, int offset)
            {
                // 密码数据
                int bufSize = (buffer != null) ? buffer.Length : 0;
                int keySize = (keys != null) ? keys.Length : 0;
                // 遍历处理
                for (int i = 0; i < bufSize; i++)
                {
                    byte b = buffer[i];
                    byte index = (byte)(indexKey - (i % indexKey));
                    byte c = (keySize > 0) ? keys[i % keySize] : (byte)0;
                    c += index;
                    // 数据转化
                    b = (byte)(b ^ c);
                    // 数据偏移
                    b = (byte)((b - (offsetKey + keySize + c) + 256) % 256);
                    // 设置数据
                    out0[i + offset] = b;
                }
                return bufSize + offset;
            }

        }

        /**
	 * 数据对调, 间隔多少数据做一次对调(相对中间)
	 * 
	 * @param source
	 *            数据源
	 * @param offset
	 *            数据偏移
	 * @param size
	 *            数据大小
	 * @param interval
	 *            间隔跳过
	 * @return
	 */
        public static byte[] Overturn(byte[] source, int offset, int size, int interval)
        {
            int count = size / 2;
            for (int i = 0; i < count; i++)
            {
                if (interval > 0 && i % (interval + 1) != 0)
                {
                    continue; // 跳过
                }
                byte b = source[offset + i];
                source[offset + i] = source[offset + size - i - 1];
                source[offset + size - i - 1] = b;
            }
            return source;
        }

        /**
         * 数组补差, 间隔多少数据进行一个^inv
         * 
         * @param source
         * @param size
         * @param interval
         * @param inv
         * @return
         */
        public static byte[] Inversion(byte[] source, int offset, int size, int interval, int inv)
        {
            int count = size;
            for (int i = 0; i < count; i++)
            {
                if (interval > 0 && i % (interval + 1) != 0)
                {
                    continue; // 跳过
                }
                source[offset + i] = (byte)(source[i + offset] ^ inv);
            }
            return source;
        }

        /**
         * 数组偏移
         * 
         * @param source
         * @param start
         * @param size
         * @param interval
         * @param offset0
         * @return
         */
        public static byte[] Offset(byte[] source, int start, int size, int interval, int offset0)
        {
            int count = size;
            for (int i = 0; i < count; i++)
            {
                if (interval > 0 && i % (interval + 1) != 0)
                {
                    continue; // 跳过
                }
                byte b = source[start + i];
                int s = (int)(0xFF) & b;
                int o = (s + offset0) % 256; // 偏移保存
                source[start + i] = (byte)o; // 转回二进制
            }
            return source;
        }

        /** 获取校验码(同样的数据应该是一样的校验码) **/
        private static int GetCheckDigit(byte[] buffer, int offset, int size)
        {
            int value = 0;
            // 遍历计算
            for (int i = 0; i < size; i++)
            {
                byte b = buffer[i + offset];
                // value = (value + b) % 98215125;
                //			value ^= b;
                value ^= b % 5;
            }

            return value;
        }

    }
}
